package com.jdrx.sw.sewage.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jdrx.platform.commons.rest.beans.vo.ResponseVO;
import com.jdrx.platform.commons.rest.exception.BizException;
import com.jdrx.platform.commons.rest.factory.ResponseFactory2;
import com.jdrx.sw.sewage.beans.dto.EnergyReportQueryDTO;
import com.jdrx.sw.sewage.beans.dto.QualityReportQueryDTO;
import com.jdrx.sw.sewage.beans.dto.QualityReportsQueryDTO;
import com.jdrx.sw.sewage.beans.dto.ReportDTO;
import com.jdrx.sw.sewage.beans.entity.DeviceTimeDataPO;
import com.jdrx.sw.sewage.beans.vo.StationEnergyReportVO;
import com.jdrx.sw.sewage.beans.vo.StationReportVO;
import com.jdrx.sw.sewage.beans.vo.base.PageVO;
import com.jdrx.sw.sewage.common.config.PathConfig;
import com.jdrx.sw.sewage.common.enums.EStationReportType;
import com.jdrx.sw.sewage.common.util.LocalDateTimeUtils;
import com.jdrx.sw.sewage.dao.DeviceTimeDataDAO;
import com.jdrx.sw.sewage.dao.StationReportDAO;
import com.jdrx.sw.sewage.service.base.BaseServiceImpl;
import com.jdrx.sw.sewage.service.common.ExcleExportService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.http.util.Asserts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class StationReportServiceImpl extends BaseServiceImpl {
    public static final Logger logger = LoggerFactory.getLogger(StationReportServiceImpl.class);

    @Autowired
    private StationReportDAO stationReportDAO;
    @Autowired
    private DeviceTimeDataDAO deviceTimeDataDao;
    @Autowired
    private DeviceTimeDataServiceImpl deviceTimeDataServiceImpl;
    @Autowired
    private ExcleExportService excleExportService;
    @Autowired
    private PathConfig pathConfig;

    public PageVO<StationReportVO> selectEnergyReportList(EnergyReportQueryDTO energyReportQueryDTO) {
        energyReportQueryDTO.setReportType(EStationReportType.ENERGY.getKey());
        PageHelper.startPage(energyReportQueryDTO);
        return PageVO.toPageVO(stationReportDAO.selectEnergyReportList(energyReportQueryDTO));
    }

    public Map<String, Object> selectQualityReportList(QualityReportQueryDTO qualityReportQueryDTO) {
        qualityReportQueryDTO.setReportType(EStationReportType.QUALITY.getKey());
        List<StationReportVO> tableData = stationReportDAO.selectQualityReportList(qualityReportQueryDTO);
        List<String> tableHead = stationReportDAO.selectQualityTableHeadList(qualityReportQueryDTO);
        HashMap map = new HashMap();
        map.put("tableHead", tableHead);
        map.put("tableData", tableData);
        return map;
    }

    public StationReportVO selectEnergyOrQualityReport(Long id) {
        return stationReportDAO.selectByPrimaryKey(id);
    }

    public ResponseVO updateEOrQReport(ReportDTO reportDTO) {
        Long id = reportDTO.getId();
        if (null == id) return ResponseFactory2.err("id不能为空");
        StationReportVO stationReportVO = stationReportDAO.selectByPrimaryKey(id);

        if (null == stationReportVO) return ResponseFactory2.err("该报表id不存在");

        stationReportVO.setJsonVal(reportDTO.getJsonVal());
        if (EStationReportType.ENERGY.getKey() == stationReportVO.getReportType()
                && LocalDateTimeUtils.getYear(stationReportVO.getCreateTime(), "Y").equals(LocalDateTimeUtils.getYear(new Date(), "Y"))) {
            //未来得数据不能修改
            JSONObject jsonVal = stationReportVO.getJsonVal();
            Integer m = LocalDateTimeUtils.getYear(new Date(), "M");
            for (int i = m; i <= 12; i++) {
                Double val = jsonVal.getDouble("" + m + "");
                if (null != val && 1 == val.compareTo(0d)) return ResponseFactory2.err("当前月及当前月以后得数据不能修改");
            }
        }
        stationReportDAO.updateByPrimaryKey(stationReportVO);
        return ResponseFactory2.ok();
    }

    /**
     * 从实时数据表sewage_device_time_data
     * 按照指定时间间隔过滤数据到sewage_station_report
     * 执行周期(每个月最后一天凌晨执行一次)
     *
     * @throws BizException
     */
   /* @Transactional(rollbackFor = Exception.class)
    public void energyReport(String dataNode) throws BizException {
        if (!StringUtils.isEmpty(dataNode)) dataNode = getSQLPerfix(dataNode);
        List<DeviceTimeDataPO> dataPOS = deviceTimeDataServiceImpl.energyReport(dataNode, DNB, null, null);
        Map<Long, List<DeviceTimeDataPO>> groupBy = dataPOS.stream().collect(Collectors.groupingBy(DeviceTimeDataPO::getStationId));

        List<StationReportPO> inDataList = new ArrayList<>();
        List<StationReportPO> upDataList = new ArrayList<>();
        for (Long mapKey : groupBy.keySet()) {
            StationReportPO stationReportPO = new StationReportPO();
            stationReportPO.setStationId(mapKey);

            AtomicReference<Double> DNB = new AtomicReference<>(0d);
            JSONObject json = new JSONObject();
            List<DeviceTimeDataPO> deviceTimeDataPOS = groupBy.get(mapKey);
            deviceTimeDataPOS.forEach(item -> {
                JSONObject jsonVal = item.getJsonVal();
                for (String jsonKey : jsonVal.keySet()) {
                    String[] keyArr = jsonKey.split("_");
                    String devStr = StringUtil.removeStrMatcher(keyArr[1]);
                    if (!devStr.contains("DNB")) continue;

                    DNB.set(DNB.get() + jsonVal.getDouble(jsonKey));
                }
            });

            //处理数据
            StationReportVO stationReportVO = stationReportDAO.selectEnergyReport(
                    LocalDateTimeUtils.getYear(new Date(), "Y").toString(),
                    mapKey, EStationReportType.ENERGY.getKey(), dataNode);

            Integer moth = LocalDateTimeUtils.getYear(new Date(), "M");
            if (!Objects.isNull(stationReportVO)) {
                stationReportPO.setId(stationReportVO.getId());
                JSONObject jsonVal = stationReportVO.getJsonVal();
                jsonVal.put(moth.toString(), DNB);
                stationReportPO.setJsonVal(jsonVal);
                upDataList.add(stationReportPO);
            } else {
                json.put(moth.toString(), DNB);
                for (int i = 1; i <= 12; i++) if (i != moth) json.put(Integer.toString(i), 0.0);

                stationReportPO.setJsonVal(json);
                stationReportPO.setReportType(EStationReportType.ENERGY.getKey());
                stationReportPO.setCreateTime(LocalDateTime.now());
                inDataList.add(stationReportPO);
            }
        }

        //批量插入&修改
        if (null != inDataList && inDataList.size() > 0) batchInsertHistory(inDataList, dataNode);
        if (null != inDataList && upDataList.size() > 0) batchUpdateHistory(upDataList, dataNode);
    }
*/
    /**
     * 从实时数据表sewage_device_time_data
     * 按照指定时间间隔过滤数据到sewage_station_report
     * 执行周期(每小时执行一次)
     *
     * @throws BizException
     */
    /*@Transactional(rollbackFor = Exception.class)
    public void qualityReport(String dataNode) throws BizException {
        if (!StringUtils.isEmpty(dataNode)) dataNode = getSQLPerfix(dataNode);

        logger.info(dataNode + "数据过滤开始，执行时间{}", LocalDateTimeUtils.localDateTime2String(LocalDateTime.now()));
        Map<String, Object> params = Maps.newHashMap();
        LocalDateTime startTime = LocalDateTime.of(LocalDate.now(), LocalTime.now().minusHours(1L).withSecond(0).withNano(0));
        LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.now().withSecond(0).withNano(0));
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        params.put("dataNode", dataNode);
        params.put("strTime", DATA_ANALYSIS_1HOUR);
        List<DeviceTimeDataPO> dataPOS = selectRealTimeLastPacksByParams(params);

        Map<Long, List<DeviceTimeDataPO>> groupBy = dataPOS.stream().collect(Collectors.groupingBy(DeviceTimeDataPO::getStationId));
        List<StationReportPO> dataList = new ArrayList<>();
        for (Long mapKey : groupBy.keySet()) {
            StationReportPO stationReportPO = new StationReportPO();
            stationReportPO.setStationId(mapKey);

            List<DeviceTimeDataPO> deviceTimeDataPOS = groupBy.get(mapKey);

            JSONObject json = new JSONObject();
            AtomicReference<Double> TJCYE = new AtomicReference<>(0d);
            AtomicReference<Double> JSSSLL = new AtomicReference<>(0d);
            AtomicReference<Double> JSLJLL = new AtomicReference<>(0d);
            AtomicReference<Double> CSCOD = new AtomicReference<>(0d);
            AtomicReference<Double> CSTN = new AtomicReference<>(0d);
            AtomicReference<Double> CSTP = new AtomicReference<>(0d);
            AtomicReference<Double> CSAD = new AtomicReference<>(0d);
            AtomicReference<Double> CSSSLL = new AtomicReference<>(0d);
            AtomicReference<Double> CSLJLL = new AtomicReference<>(0d);

            deviceTimeDataPOS.forEach(item -> {
                JSONObject jsonVal = item.getJsonVal();
                for (String jsonKey : jsonVal.keySet()) {
                    Double value = jsonVal.getDouble(jsonKey);
                    if (jsonKey.equals(TJC_YWJ_YW_Y)) TJCYE.set(value);

                    String[] keyArr = jsonKey.split("_");
                    String dev = keyArr[2];
                    if (dev.contains(DO)) {
                        if (0 == StringUtil.getStrMatcher(dev)) json.put(DOY, value);
                        else json.put(DOY + StringUtil.getStrMatcher(dev), value);
                    }

                    String pusStr = StringUtil.removeStrMatcher(keyArr[0]);
                    if (pusStr.equals(CSQ)) {
                        if (dev.contains(COD)) CSCOD.set(value);
                        if (dev.contains(TN)) CSTN.set(value);
                        if (dev.contains(TP)) CSTP.set(value);
                        if (dev.contains(NH3N)) CSAD.set(value);
                        if (dev.contains(SSLL)) CSSSLL.set(CSSSLL.get() + value);
                        if (dev.contains(LJLL)) CSLJLL.set(CSLJLL.get() + value);
                    }
                    if (pusStr.equals(JSK)) {
                        if (dev.contains(SSLL)) JSSSLL.set(JSSSLL.get() + value);
                        if (dev.contains(LJLL)) JSLJLL.set(JSLJLL.get() + value);
                    }
                }
            });
            json.put(TJCYE_CN, TJCYE);
            json.put(JSSSLL_CN, JSSSLL);
            json.put(JSLJLL_CN, JSLJLL);
            json.put(CSCOD_CN, CSCOD);
            json.put(CSTN_CN, CSTN);
            json.put(CSTP_CN, CSTP);
            json.put(CSAD_CN, CSAD);
            json.put(CSSSLL_CN, CSSSLL);
            json.put(CSLJLL_CN, CSLJLL);

            stationReportPO.setJsonVal(json);
            stationReportPO.setReportType(EStationReportType.QUALITY.getKey());
            stationReportPO.setCreateTime(LocalDateTime.now());
            dataList.add(stationReportPO);
        }
        //批量插入
        batchInsertHistory(dataList, dataNode);
    }*/
    public void batchUpdateHistory(List<Map<String, Object>> upDataList, String dataNode) throws BizException {
        int count;
        Map<String, Object> params = Maps.newHashMap();
        if (CollectionUtils.isEmpty(upDataList)) {
            return;
        }
        params.put("list", upDataList);
        params.put("dataNode", dataNode);
        count = stationReportDAO.batchUpdateHistory(params);
    }

    public void batchInsertHistory(List<Map<String, Object>> lists, String dataNode) throws BizException {
        int count;
        Map<String, Object> params = Maps.newHashMap();
        if (CollectionUtils.isEmpty(lists)) {
            return;
        }
        params.put("list", lists);
        params.put("dataNode", dataNode);
        count = stationReportDAO.batchInsertHistory(params);
    }

    public List<DeviceTimeDataPO> selectRealTimeLastPacksByParams(Map<String, Object> params) throws BizException {
        Asserts.notNull(params, "数据过滤参数");
        try {
            return deviceTimeDataDao.selectRealTimeLastPacksByParams(params);
        } catch (Exception e) {
            logger.error("数据过滤失败", e);
            throw new BizException("数据过滤失败");
        }
    }

    public void exportEnergyReport(EnergyReportQueryDTO energyReportQueryDTO, HttpServletResponse response) throws BizException {
        energyReportQueryDTO.setReportType(EStationReportType.ENERGY.getKey());
        List<StationReportVO> stationReportVOS = stationReportDAO.selectEnergyReportList(energyReportQueryDTO);

        List<StationEnergyReportVO> stationEnergyReportVOs = Lists.newArrayList();
        stationReportVOS.forEach(item -> {
            StationEnergyReportVO stationEnergyReportVO = new StationEnergyReportVO();
            stationEnergyReportVO.setStationName(item.getStationName());
            JSONObject jsonVal = item.getJsonVal();
            for (String jsonKey : jsonVal.keySet()) {
                Integer intKey = Integer.valueOf(jsonKey);
                Double value = jsonVal.getDouble(jsonKey);
                if (1 == intKey) stationEnergyReportVO.setJan(value);
                if (2 == intKey) stationEnergyReportVO.setFeb(value);
                if (3 == intKey) stationEnergyReportVO.setMar(value);
                if (4 == intKey) stationEnergyReportVO.setApr(value);
                if (5 == intKey) stationEnergyReportVO.setMay(value);
                if (6 == intKey) stationEnergyReportVO.setJun(value);
                if (7 == intKey) stationEnergyReportVO.setJul(value);
                if (8 == intKey) stationEnergyReportVO.setAug(value);
                if (9 == intKey) stationEnergyReportVO.setSept(value);
                if (10 == intKey) stationEnergyReportVO.setOct(value);
                if (11 == intKey) stationEnergyReportVO.setNov(value);
                if (12 == intKey) stationEnergyReportVO.setDec(value);
            }
            stationEnergyReportVOs.add(stationEnergyReportVO);
        });
        excleExportService.generateExcel(response, stationEnergyReportVOs, StationEnergyReportVO.class, energyReportQueryDTO.getQueryTimeStr() + "年度能耗");
    }

    public ResponseVO exportQualityReport(QualityReportsQueryDTO dto, HttpServletResponse response) throws Exception {
        dto.setReportType(EStationReportType.QUALITY.getKey());
        List<Long> stationIds = dto.getStationIds();
        if (null != stationIds && stationIds.size() <= 0) return ResponseFactory2.err("站点ids不能为空");
        Long reduceTime = LocalDateTimeUtils.timeDiff(dto.getQueryTimeStartStr(), dto.getQueryTimeEndStr());
        if (24 > reduceTime) return ResponseFactory2.err("起始时间和结束时间间隔最小为一天");

        //查询数据并按站点名称分组
        List<StationReportVO> stationReportVOs = stationReportDAO.selectStationsQualityReportList(dto);
        Map<String, List<StationReportVO>> groupBy = stationReportVOs.stream().collect(Collectors.groupingBy(StationReportVO::getStationName));

        ExcelWriter excelWriter = null;
        String fileName = pathConfig.getDownloadPath() + File.separator + System.currentTimeMillis() + ".xlsx";
        excelWriter = EasyExcel.write(fileName).build();
        int i = 0;
        try {
            for (String mapKey : groupBy.keySet()) {
                List<StationReportVO> deviceTimeDataPOS = groupBy.get(mapKey);
                QualityReportQueryDTO QualityReportQueryDTO = new QualityReportQueryDTO();
                BeanUtils.copyProperties(dto, QualityReportQueryDTO);
                QualityReportQueryDTO.setStationId(deviceTimeDataPOS.get(0).getStationId());
                //组装多个head
                List<List<String>> headLists = Lists.newArrayList();
                List<String> headList = stationReportDAO.selectQualityTableHeadList(QualityReportQueryDTO);
                List<String> newHeadList1 = Lists.newArrayList();
                newHeadList1.add("时间");
                headLists.add(newHeadList1);

                //组装每个sheet的head的数据
                List<List<Object>> dataLists = new ArrayList();

                for (int j = 0; j < deviceTimeDataPOS.size(); j++) {
                    List<Object> dataList = new ArrayList();
                    StationReportVO stationReportVO = deviceTimeDataPOS.get(j);
                    dataList.add(stationReportVO.getCreateTime());
                    JSONObject jsonVal = stationReportVO.getJsonVal();
                    for (int k = 0; k < headList.size(); k++) {
                        String head = headList.get(k);
                        if (j == 0) {
                            List<String> newHeadList = Lists.newArrayList();
                            newHeadList.add(head);
                            headLists.add(newHeadList);
                        }
                        Double v = jsonVal.getDouble(head);
                        if (null == v) dataList.add("-");
                        else dataList.add(v.toString());
                    }
                    dataLists.add(dataList);
                }
                // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
                WriteSheet writeSheet = EasyExcel.writerSheet(i, mapKey).head(headLists).build();
                excelWriter.write(dataLists, writeSheet);
                i++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (excelWriter != null) excelWriter.finish();//一定要关闭流
        }
        excleExportService.exportExcleStreamWithFileName(response, fileName);
        return ResponseFactory2.ok();
    }
}
